<template>
  <view
    class="progress"
    role="progressbar"
    :aria-valuenow="props.percentage"
    aria-valuemin="0"
    aria-valuemax="100"
  >
    <view
      class="progress-circle"
      :style="{ height: props.width + 'rpx', width: props.width + 'rpx' }"
      style="transform: rotate(90deg)"
    >
      <svg viewBox="0 0 100 100">
        <path
          class="progress-circle__track"
          :d="trackPath"
          stroke="#000000"
          :stroke-width="relativeStrokeWidth"
          fill="none"
          :stroke-linecap="props.strokeLinecap"
          :style="trailPathStyle"
        ></path>
        <defs>
          <linearGradient
            x1="0%"
            y1="100%"
            x2="100%"
            y2="100%"
            id="linearGradient-1"
          >
            <stop stop-color="#FFDA58" offset="0%"></stop>
            <stop stop-color="#FFDA58" offset="40%"></stop>
            <stop stop-color="#FF8746" offset="60%"></stop>
            <stop stop-color="#FF4023" offset="80%"></stop>
            <stop stop-color="#FE4626" offset="100%"></stop>
          </linearGradient>
        </defs>
        <!-- stroke="stroke" -->
        <path
          class="progress-circle__path"
          :d="trackPath"
          stroke="url(#linearGradient-1)"
          fill="none"
          :stroke-linecap="props.strokeLinecap"
          :stroke-width="props.percentage ? relativeStrokeWidth : 0"
          :style="circlePathStyle"
        ></path>
      </svg>
    </view>
    <view class="progress-slot">
      <uv-avatar
        v-if="props.src"
        size="112rpx"
        :src="props.src"
        mode="aspectFill"
      />
      <view class="progress-slot-text" v-else>
        <text class="text1">
          {{ colors.find(r => r.percentage === props.percentage).text1 }}
        </text>
        <text class="text2">
          {{ colors.find(r => r.percentage === props.percentage).text2 }}
        </text>
      </view>
    </view>
  </view>
</template>

<script setup>
import { ref, reactive, computed } from 'vue';
const props = defineProps({
  // 进度条画布宽度
  width: {
    type: Number,
    default: 162,
  },
  // 进度条宽度
  strokeWidth: {
    type: Number,
    default: 14,
  },
  // 百分比
  percentage: {
    type: Number,
    default: 20,
  },
  // 两端形状
  strokeLinecap: {
    type: String,
    default: 'round',
  },
  src: {
    type: String,
    default: '',
  },
});

const colors = reactive([
  { color: '#FFDA58', percentage: 20, text1: '纯纯', text2: '新人' },
  { color: '#FFDA58', percentage: 40, text1: '进阶', text2: '新手' },
  { color: '#FF8746', percentage: 60, text1: '小有', text2: '所成' },
  { color: '#FF4023', percentage: 80, text1: '崭露', text2: '头角' },
  { color: '#FE4626', percentage: 100, text1: '百炼', text2: '成钢' },
]);

const relativeStrokeWidth = computed(() => {
  return ((props.strokeWidth / props.width) * 100).toFixed(1);
});

const radius = computed(() => {
  return parseInt(50 - parseFloat(relativeStrokeWidth.value) / 2, 10);
});

const trackPath = computed(() => {
  return `
    M 50 50
    m 0 ${radius.value}
    a ${radius.value} ${radius.value} 0 1 1 0 -${radius.value * 2}
    a ${radius.value} ${radius.value} 0 1 1 0 ${radius.value * 2}
  `;
});

const perimeter = computed(() => {
  return 2 * Math.PI * radius.value;
});

const strokeDashoffset = computed(() => {
  const offset = (-1 * perimeter.value * (1 - 0.75)) / 2;
  return `${offset}px`;
});

const trailPathStyle = computed(() => {
  return {
    strokeDasharray: `${perimeter.value * 0.75}px, ${perimeter.value}px`,
    strokeDashoffset: strokeDashoffset.value,
  };
});

const circlePathStyle = computed(() => {
  return {
    strokeDasharray: `${perimeter.value * 0.75 * (props.percentage / 100)}px, ${
      perimeter.value
    }px`,
    strokeDashoffset: strokeDashoffset.value,
    transition: 'stroke-dasharray 0.6s ease 0s, stroke 0.6s ease',
  };
});

const getLevelColor = percentage => {
  const colorArray = getColorArray().sort(
    (a, b) => a.percentage - b.percentage
  );
  for (let i = 0; i < colorArray.length; i++) {
    if (colorArray[i].percentage > percentage) {
      return colorArray[i].color;
    }
  }
  return colorArray[colorArray.length - 1].color;
};

const getColorArray = () => {
  const color = colors.value;
  const span = 100 / color.length;
  return color.map((seriesColor, index) => {
    if (typeof seriesColor === 'string') {
      return {
        color: seriesColor,
        progress: (index + 1) * span,
      };
    }
    return seriesColor;
  });
};

const stroke = computed(() => {
  let ret;
  ret = getLevelColor(props.percentage);
  return ret;
});
</script>

<style lang="scss" scoped>
.progress {
  position: relative;
  line-height: 1;
  &-slot {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 112rpx;
    height: 112rpx;
    border-radius: 50%;
    background-color: #ffaf16;
    &-text {
      height: 100%;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      .text1 {
        font-size: 28rpx;
        margin-bottom: 9rpx;
      }
      .text2 {
        font-size: 35rpx;
      }
    }
  }
}
</style>
